﻿Namespace Library
  Public Class LibraryEntry
    Implements MobilePrettyGui.iPrettyListItem
    Implements ICloneable
    Implements IDisposable

    ' State info
    Private _clickRect As Rectangle = Rectangle.Empty
    Private _isSelected As Boolean = False

    ' Shared amongst all same entities
    Private Shared slc As MobilePrettyGui.PrettyList.ListColors
    Private Shared sbrBg As Brush = Nothing  ' Background normal
    Private Shared sbrBgA As Brush = Nothing ' Background alternate
    Private Shared sbrBgS As Brush = Nothing ' Background selected
    Private Shared sbrFg As Brush = Nothing  ' Foreground normal
    Private Shared sbrFg2 As Brush = Nothing ' Foreground line 2
    Private Shared sbrHL As Brush = Nothing  ' Foreground match highlight
    Private Shared sbrFgS As Brush = Nothing ' Foreground selected

    ' Data relating to library entry
    Private _avplRef As Playlists.AVPLPlaylistEntry = Nothing ' If this is assigned, draw the APPLEntry instead of the normal drawing routine
    Private _thumbnail As Bitmap = Nothing  ' Thumbnail to show on the left side
    Private _text As String = ""            ' Text to show
    Private _subtext As String = ""         ' Subtext to show on line 2
    Private _ableToQueue As Boolean = False ' Signifies if the entry can be queued or played
    Private _submenuKey As String = ""      ' The key name of the next submenu (blank if no submenu); also stores "key" for plugins
    Private _variables As List(Of Collections.Generic.KeyValuePair(Of String, String)) = Nothing
    Private _thumbnailWhere As AvianPlayDB.WhereClause = Nothing ' WHERE portion of query used to fetch album art
    Private _playlistPath As String = String.Empty ' Path to the playlist this entry represents or String.Empty if this is NOT a playlist

    ' Variables used for drawing
    Private _rf As New Drawing.Font("Tahoma", 9, Drawing.FontStyle.Regular)
    Private _bf As New Drawing.Font("Tahoma", 10, Drawing.FontStyle.Bold)
    Private _height As Integer = -1      ' Cached height (for better performance drawing)

    Public Sub New()
    End Sub

    Shared Sub New()
      slc.BackgroundColor = Color.Black
      slc.BackgroundColorAlternate = Color.Black
      slc.BackgroundColorSelected = Color.Black
      slc.NavigationFrameColor = Color.Black
      slc.TextColor1 = Color.Black
      slc.TextColor2 = Color.Black
      slc.TextColor3 = Color.Black
      slc.TextcolorSelected = Color.Black
    End Sub

    Public Sub New(ByVal le As LibraryEntry)
      Me.New()

      Me._clickRect = le._clickRect
      Me._isSelected = le._isSelected
      Me._avplRef = le._avplRef
      Me._thumbnail = le._thumbnail
      Me._text = le._text
      Me._ableToQueue = le._ableToQueue
      Me._submenuKey = le._submenuKey
      Me._variables = New List(Of Collections.Generic.KeyValuePair(Of String, String))(le.Variables)
    End Sub

    Public Shared Sub SetColors(ByVal lc As MobilePrettyGui.PrettyList.ListColors)
      If sbrBg Is Nothing OrElse slc.BackgroundColor <> lc.BackgroundColor Then
        sbrBg = New SolidBrush(lc.BackgroundColor)
      End If
      If sbrBgA Is Nothing OrElse slc.BackgroundColorAlternate <> lc.BackgroundColorAlternate Then
        sbrBgA = New SolidBrush(lc.BackgroundColorAlternate)
      End If
      If sbrBgS Is Nothing OrElse slc.BackgroundColorSelected <> lc.BackgroundColorSelected Then
        sbrBgS = New SolidBrush(lc.BackgroundColorSelected)
      End If
      If sbrBgS Is Nothing OrElse slc.BackgroundColorSelected <> lc.BackgroundColorSelected Then
        sbrBgS = New SolidBrush(lc.BackgroundColorSelected)
      End If
      If sbrFg Is Nothing OrElse slc.TextColor1 <> lc.TextColor1 Then
        sbrFg = New SolidBrush(lc.TextColor1)
      End If
      If sbrFg2 Is Nothing OrElse slc.TextColor2 <> lc.TextColor2 Then
        sbrFg2 = New SolidBrush(lc.TextColor2)
      End If
      If sbrHL Is Nothing OrElse slc.TextColor3 <> lc.TextColor3 Then
        sbrHL = New SolidBrush(lc.TextColor3)
      End If
      If sbrFgS Is Nothing OrElse slc.TextcolorSelected <> lc.TextcolorSelected Then
        sbrFgS = New SolidBrush(lc.TextcolorSelected)
      End If

      slc = lc
    End Sub


    Public Property AVPLRef() As Playlists.AVPLPlaylistEntry
      Get
        Return Me._avplRef
      End Get
      Set(ByVal value As Playlists.AVPLPlaylistEntry)
        Me._avplRef = value
        Me._height = -1
      End Set
    End Property

    Public Property Thumbnail() As Bitmap
      Get
        Return Me._thumbnail
      End Get
      Set(ByVal value As Bitmap)
        If Me._thumbnail IsNot Nothing Then
          Me._thumbnail.Dispose()
          Me._thumbnail = Nothing
        End If
        Me._thumbnail = value
      End Set
    End Property

    Public Property Text() As String
      Get
        Return Me._text
      End Get
      Set(ByVal value As String)
        Me._text = value
        Me._height = -1
      End Set
    End Property

    Public Property Subtext() As String
      Get
        Return Me._subtext
      End Get
      Set(ByVal value As String)
        Me._subtext = value
        Me._height = -1
      End Set
    End Property

    Public Property AbleToQueue() As Boolean
      Get
        Return Me._ableToQueue
      End Get
      Set(ByVal value As Boolean)
        Me._ableToQueue = value
      End Set
    End Property

    Public Property SubmenuKey() As String
      Get
        Return Me._submenuKey
      End Get
      Set(ByVal value As String)
        Me._submenuKey = value
      End Set
    End Property

    Public Property Variables() As List(Of Collections.Generic.KeyValuePair(Of String, String))
      Get
        Return Me._variables
      End Get
      Set(ByVal value As List(Of Collections.Generic.KeyValuePair(Of String, String)))
        Me._variables = value
      End Set
    End Property

    Public ReadOnly Property ThumbnailQuery() As String
      Get
        If Me._thumbnailWhere IsNot Nothing AndAlso Me._thumbnailWhere.Count > 0 Then
          Dim ret As String = "SELECT TOP(1) FilePath FROM FileLibrary WHERE "

          For i As Integer = 0 To Me._thumbnailWhere.Count - 1
            If i > 0 Then ret &= " AND "
            ret &= Me._thumbnailWhere.SQLCEWhereClause(i)
          Next

          Return ret
        Else
          Return Nothing
        End If
      End Get
    End Property

    Public ReadOnly Property ThumbnailParameters() As List(Of Data.SqlServerCe.SqlCeParameter)
      Get
        If Me._thumbnailWhere IsNot Nothing AndAlso Me._thumbnailWhere.Count > 0 Then
          Dim tps As New List(Of Data.SqlServerCe.SqlCeParameter)
          For i As Integer = 0 To Me._thumbnailWhere.Count - 1
            tps.Add(Me._thumbnailWhere.SQLCEParameter(i))
          Next
          Return tps
        Else
          Return Nothing
        End If
      End Get
    End Property

    ''' <summary>
    ''' Sets up the query used to retrieve the thumbnails for list.  This should be called AFTER all variables are set for proper parsing.
    ''' </summary>
    Public Sub SetThumbnailQueryWhere(ByVal where As AvianPlayDB.WhereClause)
      Dim removeWhere As New List(Of AvianPlayDB.WhereClause.WhereItem)

      For Each w As AvianPlayDB.WhereClause.WhereItem In where.WhereItems
        w.ValueString = w.ValueString.ToUpper
        For Each kv As KeyValuePair(Of String, String) In Me._variables
          Dim k As String = "{" & kv.Key.ToUpper & "}"
          w.ValueString = w.ValueString.Replace(k, kv.Value)
        Next
        If w.ValueString.Contains("{"c) OrElse w.ValueString.Contains("}"c) Then
          removeWhere.Add(w)
        End If
      Next

      For Each w As AvianPlayDB.WhereClause.WhereItem In removeWhere
        where.WhereItems.Remove(w)
      Next

      If where.Count > 0 Then
        Me._thumbnailWhere = where
      End If
    End Sub

    Public Property ClickRectangle() As System.Drawing.Rectangle Implements MobilePrettyGui.iPrettyListItem.ClickRectangle
      Get
        Return Me._clickRect
      End Get
      Set(ByVal value As System.Drawing.Rectangle)
        Me._clickRect = value
      End Set
    End Property

    Public ReadOnly Property IsPlaylist() As Boolean
      Get
        Return Me._playlistPath IsNot Nothing AndAlso Me._playlistPath.Length > 0
      End Get
    End Property

    Public Property PlaylistPath() As String
      Get
        Return Me._playlistPath
      End Get
      Set(ByVal value As String)
        Me._playlistPath = value
      End Set
    End Property

    Public Sub DrawPrettyListItem(ByVal g As System.Drawing.Graphics, ByVal dpiFactor As Single, ByVal colors As MobilePrettyGui.PrettyList.ListColors, ByVal rect As System.Drawing.Rectangle, ByVal isAlternate As Boolean) Implements MobilePrettyGui.iPrettyListItem.DrawPrettyListItem
      ' Check shared colors
      SetColors(colors)

      If Me._avplRef IsNot Nothing Then
        Me._avplRef.IsSelected = Me._isSelected
        Me._avplRef.ClickRectangle = Me._clickRect
        Me._avplRef.DrawPrettyListItem(g, dpiFactor, colors, rect, isAlternate)
      Else
        Dim brBg As Brush
        Dim brBgA As Brush
        Dim brFg As Brush
        Dim brFg2 As Brush
        Dim brHL As Brush

        If Me._isSelected Then
          brBg = sbrBgS
          brBgA = sbrBgS
          brFg = sbrFgS
          brFg2 = sbrFgS
          brHL = sbrFgS
        Else
          brBg = sbrBg
          brBgA = sbrBgA
          brFg = sbrFg
          brFg2 = sbrFg2
          brHL = sbrHL
        End If

        Dim sfText As Drawing.SizeF = g.MeasureString(Me._text, Me._bf)
        Dim sfSubtext As Drawing.SizeF = g.MeasureString(Me._subtext, Me._rf)
        Dim y As Integer = (rect.Height - (sfText.Height + sfSubtext.Height + (2 * dpiFactor))) / 2

        g.FillRectangle(IIf(isAlternate, brBgA, brBg), rect)


        ' Draw the thumbnail
        Dim txtPadWidth As Integer = 0

        If AvianPlay.Playlists.AVPLPlaylistEntry.AlbumArtListDisplayMode <> AvianPlay.Playlists.AVPLPlaylistEntry.AlbumArtListDisplayModeEnum.NoAlbumArt Then
          Dim imgWidth As Integer = rect.Height - (4 * dpiFactor)
          Dim imgHeight As Integer
          Dim imgY As Integer = 0

          If Me._thumbnail IsNot Nothing Then
            imgHeight = (imgWidth / Me._thumbnail.Width) * Me._thumbnail.Height
            If imgHeight < Me._height Then imgY = (Me._height - imgHeight) >> 1 ' Vertically center the album art if it's 'wide'
            g.DrawImage(Me._thumbnail, New Rectangle(rect.X + (2 * dpiFactor), rect.Y + imgY, imgWidth, imgHeight), New Rectangle(0, 0, Me._thumbnail.Width, Me._thumbnail.Height), GraphicsUnit.Pixel)
            txtPadWidth = rect.X + rect.Height + (2 * dpiFactor)
          ElseIf AvianPlay.Playlists.AVPLPlaylistEntry.AlbumArtListDisplayMode = AvianPlay.Playlists.AVPLPlaylistEntry.AlbumArtListDisplayModeEnum.AlwaysIndent Then
            ' TODO: Draw "no thumbnail" thumbnail
            txtPadWidth = rect.X + rect.Height + (2 * dpiFactor)
          End If
        End If

        If Playlists.AVPLPlaylistEntry.SearchTerm.Length > 0 Then
          Playlists.AVPLPlaylistEntry.DrawHighlight(Me._text, Me._bf, brFg, brHL, g, rect.X + txtPadWidth, rect.Y + y)
          Playlists.AVPLPlaylistEntry.DrawHighlight(Me._subtext, Me._rf, brFg2, brHL, g, rect.X + txtPadWidth, rect.Y + y + (sfText.Height) + (2 * dpiFactor))
        Else
          g.DrawString(Me._text, Me._bf, brFg, rect.X + txtPadWidth, rect.Y + y)
          g.DrawString(Me._subtext, Me._rf, brFg2, rect.X + txtPadWidth, rect.Y + y + (sfText.Height) + (2 * dpiFactor))
        End If
      End If
    End Sub

    Public Function DrawPrettyListItemHeight(ByVal g As System.Drawing.Graphics, ByVal dpiFactor As Single) As Integer Implements MobilePrettyGui.iPrettyListItem.DrawPrettyListItemHeight
      If Me._height < 0 Then
        If Me._avplRef IsNot Nothing Then
          Me._avplRef.IsSelected = Me._isSelected
          Me._avplRef.ClickRectangle = Me._clickRect
          Me._height = Me._avplRef.DrawPrettyListItemHeight(g, dpiFactor)
        Else
          Dim sfText As Drawing.SizeF = g.MeasureString("Pp", Me._bf)
          Dim sfSubtext As Drawing.SizeF = g.MeasureString("Pp", Me._rf)
          Me._height = sfText.Height + sfSubtext.Height + (6 * dpiFactor)
        End If
      End If

      Return Me._height
    End Function

    Public Property IsSelected() As Boolean Implements MobilePrettyGui.iPrettyListItem.IsSelected
      Get
        Return Me._isSelected
      End Get
      Set(ByVal value As Boolean)
        Me._isSelected = value
      End Set
    End Property

    Public ReadOnly Property FilterIsIncluded(ByVal filter As String) As Boolean Implements MobilePrettyGui.iPrettyListItem.FilterIsIncluded
      Get
        If Me._avplRef IsNot Nothing Then
          Return Me._avplRef.FilterIsIncluded(filter)
        Else
          If Me._text.ToUpper.Contains(filter) Then Return True
          If Me._subtext.ToUpper.Contains(filter) Then Return True
        End If
        Return False
      End Get
    End Property

    Public Sub OnMouseClick() Implements MobilePrettyGui.iPrettyListItem.OnMouseClick
      Me._isSelected = False
    End Sub

    Public Sub OnMouseLongClick() Implements MobilePrettyGui.iPrettyListItem.OnMouseLongClick
      Me._isSelected = False
    End Sub

    Public Sub OnMouseDown() Implements MobilePrettyGui.iPrettyListItem.OnMouseDown
      Me._isSelected = True
    End Sub

    Public Sub OnMouseUp() Implements MobilePrettyGui.iPrettyListItem.OnMouseUp
      Me._isSelected = False
    End Sub

    Public Sub OnMouseScroll() Implements MobilePrettyGui.iPrettyListItem.OnMouseScroll
      Me._isSelected = False
    End Sub

    Public Function Clone() As Object Implements System.ICloneable.Clone
      Return New LibraryEntry(Me)
    End Function

#Region " IDisposable Support "
    Private disposedValue As Boolean = False    ' To detect redundant calls
    ' IDisposable
    Protected Overridable Sub Dispose(ByVal disposing As Boolean)
      If Not Me.disposedValue Then
        If disposing Then
          If Me._thumbnail IsNot Nothing Then
            Me._thumbnail.Dispose()
            Me._thumbnail = Nothing
          End If
        End If
      End If
      Me.disposedValue = True
    End Sub

    ' This code added by Visual Basic to correctly implement the disposable pattern.
    Public Sub Dispose() Implements IDisposable.Dispose
      ' Do not change this code.  Put cleanup code in Dispose(ByVal disposing As Boolean) above.
      Dispose(True)
      GC.SuppressFinalize(Me)
    End Sub
#End Region
  End Class
End Namespace